﻿Imports Microsoft.VisualBasic
Imports Microsoft.VisualBasic.CompilerServices
Imports Stickam_Client.My
Imports System
Imports System.Diagnostics
Imports System.Runtime.CompilerServices

Namespace Stickam_Client
    Public Class StickamRtmp
        ' Events
        Public Custom Event Closed As ClosedEventHandler
        Public Custom Event Connected As ConnectedEventHandler
        Public Custom Event DataArrival As DataArrivalEventHandler
        Public Custom Event HandshakeReply As HandshakeReplyEventHandler

        ' Methods
        Public Sub New()
            Me.RtmpSocket = New SocketConnector
            Me.EnableDataflow = True
            Me.SendEnabled = True
        End Sub

        Public Sub Close()
            Me.CloseConnection("Client closed the connection.")
        End Sub

        Private Sub CloseConnection(ByVal Reason As String)
            Me.RtmpSocket.Close
            Dim closedEvent As ClosedEventHandler = Me.ClosedEvent
            If (Not closedEvent Is Nothing) Then
                closedEvent.Invoke(Reason)
            End If
        End Sub

        Public Sub Connect(ByVal RoomIP As String)
            Me.FirstPacket = True
            Me.FirstPacketData = ""
            Me.LastData = ""
            Me.LastCommand = New String(&H40  - 1) {}
            Me.LastLength = New String(&H40  - 1) {}
            Me.RtmpSocket.Connect(RoomIP, MySettingsProperty.Settings.SocksIP, MySettingsProperty.Settings.SocksVersion, MySettingsProperty.Settings.SocksRTMP)
        End Sub

        Private Sub ParseData(ByVal Data As String)
            Data = (Me.LastData & Data)
            Me.LastData = ""
            Dim num As Integer = Strings.Asc(Strings.Mid(Data, 1, 1))
            Dim num2 As Integer = Me.HeaderLengths((num >> 6))
            Dim index As Integer = num
            If (index >= &H80) Then
                index = (index - &H80)
            End If
            If (index >= &H40) Then
                index = (index - &H40)
            End If
            If (Data.Length >= num2) Then
                Dim num4 As Integer
                Dim num7 As Integer
                Dim num5 As Integer = 0
                Dim num6 As Integer = 0
                Dim num8 As Integer = 0
                Dim num9 As Integer = 0
                If (num2 >= 4) Then
                    num9 = Globals.BytesToInt(Strings.Mid(Data, 2, 3))
                End If
                If (num2 >= 8) Then
                    num6 = Globals.BytesToInt(Strings.Mid(Data, 5, 3))
                    num5 = Strings.Asc(Strings.Mid(Data, 8, 1))
                End If
                If (num2 = 12) Then
                    num8 = Globals.BytesToInt(Strings.Mid(Data, 9, 4))
                End If
                If (num2 < 8) Then
                    num5 = Conversions.ToInteger(Me.LastCommand(index))
                    num6 = Conversions.ToInteger(Me.LastLength(index))
                End If
                Me.LastCommand(index) = Conversions.ToString(num5)
                Me.LastLength(index) = Conversions.ToString(num6)
                If (num9 = &HFFFFFF) Then
                    num7 = &H85
                    num4 = CInt(Math.Round(CDbl(((Conversion.Fix(CDbl((CDbl((num6 - 1)) / 128))) * 5) + 4))))
                Else
                    num7 = &H81
                    num4 = CInt(Math.Round(Conversion.Fix(CDbl((CDbl((num6 - 1)) / 128)))))
                End If
                num6 = (num6 + num4)
                Dim num10 As Integer = (num2 + num6)
                If (Data.Length >= num10) Then
                    Dim dataArrivalEvent As DataArrivalEventHandler = Me.DataArrivalEvent
                    If (Not dataArrivalEvent Is Nothing) Then
                        dataArrivalEvent.Invoke(num5, Globals.CleanSplitters(Strings.Mid(Data, (num2 + 1), num6), num7))
                    End If
                    Dim data As String = Strings.Mid(Data, (num10 + 1))
                    If (data.Length > 0) Then
                        Me.ParseData(data)
                    End If
                Else
                    Me.LastData = Data
                End If
            Else
                Me.LastData = Data
            End If
        End Sub

        Public Sub ResetParser()
            Me.LastData = ""
        End Sub

        Private Sub RtmpSocket_Closed()
            Me.CloseConnection("Server closed the connection.")
        End Sub

        Private Sub RtmpSocket_Connected()
            Dim connectedEvent As ConnectedEventHandler = Me.ConnectedEvent
            If (Not connectedEvent Is Nothing) Then
                connectedEvent.Invoke
            End If
            Me.SendData(Globals.RtmpHandshake)
        End Sub

        Private Sub RtmpSocket_ConnectFail()
            Me.CloseConnection("Could not establish a connection.")
        End Sub

        Private Sub RtmpSocket_DataArrival(ByVal Data As String)
            If Me.EnableDataflow Then
                If Me.FirstPacket Then
                    Me.FirstPacketData = (Me.FirstPacketData & Data)
                    If ((Strings.Asc(Strings.Mid(Me.FirstPacketData, 1, 1)) = 3) And (Me.FirstPacketData.Length = &HC01)) Then
                        Me.FirstPacket = False
                        Dim handshakeReplyEvent As HandshakeReplyEventHandler = Me.HandshakeReplyEvent
                        If (Not handshakeReplyEvent Is Nothing) Then
                            handshakeReplyEvent.Invoke(Strings.Mid(Me.FirstPacketData, 2, &H600))
                        End If
                    ElseIf (Me.FirstPacketData.Length >= &HC01) Then
                        Me.CloseConnection("Bad handshake reply from server. Connection closed.")
                    End If
                ElseIf (Data.Length <> 0) Then
                    Me.ParseData(Data)
                End If
            End If
        End Sub

        Public Sub SendData(ByVal Data As String)
            If Me.SendEnabled Then
                Me.RtmpSocket.SendData(Data)
            End If
        End Sub


        ' Properties
        Private Overridable Property RtmpSocket As SocketConnector
            Get
                Return Me._RtmpSocket
            End Get
            Set(ByVal WithEventsValue As SocketConnector)
                Dim handler As DataArrivalEventHandler = New DataArrivalEventHandler(AddressOf Me.RtmpSocket_DataArrival)
                Dim handler2 As ConnectFailEventHandler = New ConnectFailEventHandler(AddressOf Me.RtmpSocket_ConnectFail)
                Dim handler3 As ConnectedEventHandler = New ConnectedEventHandler(AddressOf Me.RtmpSocket_Connected)
                Dim handler4 As ClosedEventHandler = New ClosedEventHandler(AddressOf Me.RtmpSocket_Closed)
                If (Not Me._RtmpSocket Is Nothing) Then
                    RemoveHandler Me._RtmpSocket.DataArrival, handler
                    RemoveHandler Me._RtmpSocket.ConnectFail, handler2
                    RemoveHandler Me._RtmpSocket.Connected, handler3
                    RemoveHandler Me._RtmpSocket.Closed, handler4
                End If
                Me._RtmpSocket = WithEventsValue
                If (Not Me._RtmpSocket Is Nothing) Then
                    AddHandler Me._RtmpSocket.DataArrival, handler
                    AddHandler Me._RtmpSocket.ConnectFail, handler2
                    AddHandler Me._RtmpSocket.Connected, handler3
                    AddHandler Me._RtmpSocket.Closed, handler4
                End If
            End Set
        End Property


        ' Fields
        Private _RtmpSocket As SocketConnector
        Public EnableDataflow As Boolean
        Private FirstPacket As Boolean
        Private FirstPacketData As String
        Private HeaderLengths As Integer() = New Integer() { 12, 8, 4, 1 }
        Private LastCommand As String() = New String(&H40  - 1) {}
        Private LastData As String
        Private LastLength As String() = New String(&H40  - 1) {}
        Private PacketCountIn As Integer = 0
        Private PacketCountOut As Integer = 0
        Public SendEnabled As Boolean

        ' Nested Types
        Public Delegate Sub ClosedEventHandler(ByVal Reason As String)

        Public Delegate Sub ConnectedEventHandler()

        Public Delegate Sub DataArrivalEventHandler(ByVal Command As Integer, ByVal Data As String)

        Public Delegate Sub HandshakeReplyEventHandler(ByVal HandshakeData As String)
    End Class
End Namespace

